package com.tedu.API.io;

import org.junit.Test;

import java.io.*;

/**
 * 标准IO流----目的：数据传输  输出文本、图片
 * java定义一套标准流-->数据传输-->创建流：直接创建某个流对象。
 * 标准流规则：①方向划分---输入流和输出流
 *            输入流：  读入-->文件-->相对于程序--->文件往程序走
 *            InputStream(抽象类：定义所有 读的写法)【学习：子实现类】
 *            输出流：  写-->文件--->相对于程序--->程序写出
 *            OutputStream(抽象类：定义所有写的方法)【学习：子实现类】
 *          ②功能划分
 *          低级流【节点流】：是建立在程序与数据源之间的"管道"
 *                   功能：负责搬运的数据流，输入流于输出流都有自己的低级流
 *                   特点：一个字节一个字节读或者写的方法
 *          FileOutputStream  低级流继承InputStream---文件输出流：写
 *          FileInputStream   低级流继承OutputStream--文件输入流：读
 *          高级流【处理流】：不能直接创建对象，不能独立存在。
 *                    功能：专门处理低级流以及其他高级流的流
 *                    特点：搬运数据时，实现具体功能：效率提高流
 *
 * --总结：输入流和输出流，具备功能：低级流与高级流，
 * 实际使用：明确使用具体流，每个流都有自己功能
 *
 */
public class IOAPI {
    /**
     *                                      文件输入流
     *              输入流           低级流---
     * 标准流  方向          功能：            文件输出流：FileOutputStream
     *              输出流           高级流
     *  需求：才写出一个文件 fos.txt
     *
     *  new FileOutputStream 构造器使用("路径+文件全称")
     *  new FileOutputStream 构造器使用("路径+文件全称",boolean append)
     *  写出文件的同时实现追加效果,第二个参数:true  追加
     *                                  false  默认不追加
     *  new FileOutputStream(File file,boolean append)
     *  写出文件，采用File传入路径+全称
     */
    @Test
    public void testFOS()  {
     //   RandomAccessFile randomAccessFile=new RandomAccessFile("fos.txt","rw");
        //低级流---文件输出流对象----从程序中写出"文件：数据"
        FileOutputStream fos=null;
        try {
            fos=new FileOutputStream("fos.txt",true);
            fos.write("独one无two".getBytes());
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            if(fos!=null)
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
        //需求：fos.txt 增加一行文本，每次运行实现追加效果
        String say="独one无two";
        //字符串由字符数组构成---数组的功能--getBytes()转换为字节数组
        //输出流--写功能：write(byte[] b) 写出字节数组
    //    fos.write(say.getBytes("UTF8"));
        //必须关闭流---目的：节省内存开销
    //    fos.close();
    }
    /**
     * 文件输入流：读入操作
     * FileInputStream 文件输入流
     * read() 返回一个读取的一个字节---效率低
     * read(字节数组byte[] b)
     * 返回一个“指定字节数组：空间大小”的读取---效率高
     * 需求：读入fos.txt文件内容
     */
    @Test
    public void testFIS()  {
        //创建文件输入流---读入：fos.txt
        FileInputStream fis=null;
        byte[] data= new byte[0];
        int len= 0;
        try {
            fis=new FileInputStream("fos.txt");
            //读入效率高：10KB
            data = new byte[1024*10];
            //读入操作：read(字节数组)|以10KB读入数据
            len = fis.read(data);
        } catch (FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            if (fis!=null)
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
        //写出：文本---字符串---针对流操作，提供构造器
       //                      文件按照"指定字节数组空间"写入程序中
       //                      从0开始写入程序,写入到-1结束
       //                      len:十进制转换位二进制，写入，不等-1，一直写入
       //一次性将给定数据按照字节数组指定空间大小，写出成字符串
        String str=new String(data,0,len);
       System.out.println("打印fos.txt文件："+str);
    }
    @Test
    public void testCV()  {
        //1.从“复制文件.mp4” 复制 操作----读入
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try {
            fis=new FileInputStream("复制视频.mp4");
            //2.创建新文件"新文件.mp4" 粘贴 操作---写出

            fos=new FileOutputStream("新文件.mp4",true);
            //3.保存每次读取的数据【字节量---int】
            int len=-1;
            byte[] data=new byte[1024];
            //4.一直 从"复制文件.mp4" 进行读入操作,不等于-1  一直读
            while( (len=fis.read(data))!=-1){
                fos.write(data,0,len);
            }
        } catch (FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {

        //4.1同时 写出 "新文件.mp4"

        //5.关闭流
        if (fis!=null)
        try {
                fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(fos!=null)
        try {
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
    }
    /**
     * 需求：利用标准流实现视频复制粘贴--效率低
     *                              效率高--->空间执行为：自定100KB
     *
     * 【高级流】BufferedInputStream  缓冲输入流--提升效率，内嵌缓冲区：字节数组【长度按照文件大小合理分配】
     *         BufferedOutputStream 缓冲输出流--提升效率，内嵌缓冲区：字节数组【长度按照文件大小合理分配】
     *  高级流使用方式：①处理低级流，套在低级流上
     *            写法：new 高级流(传入低级流引用)
     *               ②直接使用高级流的方法
     *               ③高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS()  {
        //创建低级流：读入“视频.mp4”
        FileInputStream fis=null;
        //创建高级流：套在低级流上【自带缓冲区：字节数组】
        BufferedInputStream bis=null;

        //2.创建低级流:写出“高效视频.mp4”
        FileOutputStream fos=null;
        //3.创建高级流：套在低级流上【自带缓冲区：字节数组】
        BufferedOutputStream bos=null;

        try {
            fis=new FileInputStream("复制视频.mp4");
            bis=new BufferedInputStream(fis);
            fos=new FileOutputStream("高效视频.mp4");
            bos=new BufferedOutputStream(fos);
            //4.保存数据
            int len=-1;

            //5.高级流--低级流方法一致---read()读取内嵌缓冲区【字节数组】
            //  高级流--低级流方法一致---write()写出内嵌缓冲区【字节数组】
            //一直从"复制视频.mp4"读取数据，不等于-1，一直读
            //(len=bis.read())!=-1
            long start=System.currentTimeMillis();//系统时间毫秒数
            while((len=bis.read())!=-1){
                bos.write(len);
            }
            long end=System.currentTimeMillis();
            System.out.println("缓冲流【自带缓冲区】："+(end-start)+"毫秒数");
        }
        catch (FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {

            //关闭流--  高级流与低级流：都管--->高级流间接性关闭低级流--->关闭高级流
            if (bis != null)
                try {
                    bis.close();//高级流--缓冲输入流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if (bos != null)
                try {
                    bos.close();//高级流--缓冲输出流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if (fis != null)
                try {
                    fis.close();//低级流--缓冲输入流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            if (fos != null)
                try {
                    fos.close();//低级流--缓冲输出流
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    }

    /**
     * 高级流---缓冲流【内嵌缓冲区】
     * BufferedOutputStream  缓冲输出流
     *
     * 需求：通过缓冲输出流实现冲程序写出文件：bos.txt,写出内容
     */
    @Test
    public void testBOS() throws IOException {
        //1.创建低级流---bos.txt
        FileOutputStream fos=new FileOutputStream("bos.txt");
        //2.创建高级流--->缓冲区：字节数组--合理【传输效率】
        BufferedOutputStream bos=new BufferedOutputStream(fos);
        //3.写出文本内容
        String str="贾京彩 再怎么彩也是菜 毕竟京菜本来就是菜 你懂吧";
        //4.写出到 bos.txt 文件中 ：字符串转换成字节数字--写出
        bos.write(str.getBytes());
        //5.将缓冲区数据一次性写出 flush() 【立即写出】
       // bos.flush();
        bos.close(); //关闭流---一定把缓冲区数据全部写出


    }

    /**
     * 标准IO---成对【低级流+高级流】结合异常---数据传输---成功【异常需要捕获】
     * 需求：重构 testBOS() 单元测试
     */
    @Test
    public void testBOSIO(){
        //1.置空流----提升所以流作用域：使用范围
        FileOutputStream fos=null;  //低级流：搬运数据
        BufferedOutputStream bos=null; //高级流：缓冲输出流
        //2.捕获流异常 并且做出处理
        try {
            fos=new FileOutputStream("bos.txt");//低级流
            bos=new BufferedOutputStream(fos);//高级流：缓冲区：字节数组
            bos.write("贾京彩 再怎么彩也是菜 毕竟京菜本来就是菜 你懂吧".getBytes());
            bos.flush();
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) { //IO流 "中"异常：小异常的父类
            e.printStackTrace();
        }catch (Exception e){// “大” 异常  Exception
            e.printStackTrace();
        }
        finally {
            //3.关闭流---高级流--释放资源
            //判断：高级流是否为null，如果不为null，关闭
            if(bos!=null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }


}
